﻿using System;
using EnterpriseLibraryExtensions.Events;
using EnterpriseLibraryExtensions.Events.Aggregation;
using Microsoft.Practices.Unity;

namespace EventHandling
{
    class Program
    {
        static void Main()
        {
            SimpleRun();

            ScopedRun();

            AsyncHandlersRun();

            AggregateIntelligently();
        }

        private static void SimpleRun()
        {
            /////////////////////////////////////////////////////////////////////
            // The following demonstrates how to register the eventing mechanism
            // in an existing Unity Container.
            /////////////////////////////////////////////////////////////////////

            var container = new UnityContainer();
            EventManager.RegisterInContainer(container);

            // Extracing the event registration manager.

            var eventRegistrationManager = container.Resolve<IEventRegistration>();

            // Register an event handler class.

            eventRegistrationManager.Register<SampleEventType, SampleEventHandler>();

            // Register a delegate as event handler.

            eventRegistrationManager.Register<SampleEventType>((sender, args) => Console.WriteLine(@"Event handled inline. Parameter: " + args.Value.EventValue));

            // Raise event!

            var eventProducer = container.Resolve<IEventProducer>();

            eventProducer.Raise(null, new SampleEventType("Hello World"));
        }

        private static void ScopedRun()
        {
            /////////////////////////////////////////////////////////////////////
            // The following demonstrates how to use event aggregation within 
            // a scope. When the scope completes, only one event will be fired.
            /////////////////////////////////////////////////////////////////////

            var container = new UnityContainer();
            EventManager.RegisterInContainer(container);

            // Extracing the event registration manager.

            var eventRegistrationManager = container.Resolve<IEventRegistration>();

            // Register an event handler class.

            eventRegistrationManager.Register<SampleEventType, SampleEventHandler>();

            // Register a delegate as event handler.

            eventRegistrationManager.Register<SampleEventType>((sender, args) => Console.WriteLine(@"Event handled inline. Parameter: " + args.Value.EventValue));

            using (var scope = new EventAggregationScope())
            {
                scope.Options = new TypeFilteringScopeOptions();

                // Raise event!

                var eventProducer = container.Resolve<IEventProducer>();

                eventProducer.Raise(null, new SampleEventType("Hello World"));

                scope.Complete();
            }
        }

        private static void AsyncHandlersRun()
        {
            //////////////////////////////////////////////////////////////////////
            // The following code demonstrates how to invoke async event handlers.
            // Please note that event though an event handlers is reporting that
            // it can do async processing it is not guaranteed to be invoked on
            // another thread. That is determined by ParallelFx.
            //////////////////////////////////////////////////////////////////////

            var container = new UnityContainer();
            EventManager.RegisterInContainer(container);

            // Extracing the event registration manager.

            var eventRegistrationManager = container.Resolve<IEventRegistration>();

            eventRegistrationManager.Register<SampleEventType, SampleEventHandlerAsync>();

            // Raise event!

            var eventProducer = container.Resolve<IEventProducer>();

            eventProducer.Raise(null, new SampleEventType("Hello World"));
        }

        private static void AggregateIntelligently()
        {
            //////////////////////////////////////////////////////////////////////
            // The following code demonstrates how to apply intelligent filtering
            // when aggregating events. In the sample, events are filtered on the
            // event value being passed which means that only two events will be
            // raised event though three events are raised.
            //////////////////////////////////////////////////////////////////////

            var container = new UnityContainer();
            EventManager.RegisterInContainer(container);
            
            // Extracing the event registration manager.

            var eventRegistrationManager = container.Resolve<IEventRegistration>();

            eventRegistrationManager.Register<SampleEventType, SampleEventHandler>();

            // Create an aggregation scope and register the sample comparer.

            using (var scope = new EventAggregationScope())
            {
                var options = new FilteringScopeOptions();
                options.RegisterComparer(new SampleEventTypeComparer());

                scope.Options = options;

                // Raise events!

                var eventProducer = container.Resolve<IEventProducer>();

                eventProducer.Raise(null, new SampleEventType("Hello World"));
                eventProducer.Raise(null, new SampleEventType("Some other Statement"));
                eventProducer.Raise(null, new SampleEventType("Hello World"));

                scope.Complete();
            }
        }
    }
}
